package com.punai.customer.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageInfo;
import com.punai.common.core.domain.entity.SysDictData;
import com.punai.common.core.page.TableDataInfo;
import com.punai.common.exception.ServiceException;
import com.punai.common.utils.*;
import com.punai.customer.domain.*;
import com.punai.customer.domain.bo.CJFlRes;
import com.punai.customer.domain.bo.CusFeatureBo;
import com.punai.customer.domain.bo.FeatureRes;
import com.punai.customer.domain.bo.FeeLinkFeatureAndCategoryResultBo;
import com.punai.customer.domain.contants.CusConstants;
import com.punai.customer.domain.request.CusRewriteCodeRequest;
import com.punai.customer.domain.vo.BasicInfoVo;
import com.punai.customer.domain.vo.CusFeatureStateVo;
import com.punai.customer.domain.vo.GxFeeVo;
import com.punai.customer.mapper.*;
import com.punai.customer.service.ICusGxFeeService;
import com.punai.standard.domain.StaGxFee;
import com.punai.standard.mapper.StaGxChapterMapper;
import com.punai.standard.mapper.StaGxFeeMapper;
import com.punai.standard.mapper.StaVersionMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 工序分包费用项Service业务层处理
 *
 * @author zxw
 * @date 2022-12-09
 */
@Service
public class CusGxFeeServiceImpl extends ServiceImpl<CusGxFeeMapper, CusGxFee> implements ICusGxFeeService
{
    @Autowired
    private CusGxFeeMapper cusGxFeeMapper;

    @Autowired
    private CusGxChapterMapper cusGxChapterMapper;

    @Autowired
    private CusLinkFeatureMapper cusLinkFeatureMapper;

    @Autowired
    private CusLinkGxfeeCategoryMapper cusLinkGxfeeCategoryMapper;
    @Autowired
    private CusLinkSubpkConsumeMapper cusLinkSubpkConsumeMapper;
    @Autowired
    private CusLinkSubpkConsumeAddressMapper cusLinkSubpkConsumeAddressMapper;
    @Autowired
    private StaVersionMapper staVersionMapper;
    @Autowired
    private CusVersionsDiscrepancyMapper cusVersionsDiscrepancyMapper;
    @Autowired
    private StaGxChapterMapper staGxChapterMapper;
    @Autowired
    private StaGxFeeMapper staGxFeeMapper;
    @Autowired
    private CusGxLinkGkCategoriesMapper cusGxLinkGkCategoriesMapper;
    @Autowired
    private CusGxLinkGkMapper cusGxLinkGkMapper;
    @Autowired
    private CusGxFeatureConsumeMapper cusGxFeatureConsumeMapper;
    /**
     * 查询工序分包费用项
     *
     * @param id 工序分包费用项主键
     * @return 工序分包费用项
     */
    @Override
    public CusGxFee selectDmcGxFeeById(String id)
    {
        return null;
    }

    /**
     * 查询工序分包费用项列表
     *
     * @param dmcGxFee 工序分包费用项
     * @param companyId
     * @return 工序分包费用项
     */
    @Override
    public TableDataInfo selectDmcGxFeeList(CusGxFee dmcGxFee, Long companyId)
    {
        String chapterId = dmcGxFee.getChapterId();
        List<String> chapterIds = new ArrayList<>();

        if(!StringUtils.equals(chapterId,CusConstants.CHAPTER_ID_NULL)){
            dmcGxFee.setSpecId(null);
            chapterIds = cusGxChapterMapper.selectChildrenIdById(chapterId, companyId);
        }else {
            if (StrUtil.isEmpty(dmcGxFee.getSpecId())) {
                throw new RuntimeException("专业获取失败");
            }
        }
        chapterIds.add(0, chapterId);

        PageUtils.startPage();
        List<CusGxFee> gxFees = cusGxFeeMapper.selectDmcGxFeeList(dmcGxFee, chapterIds, companyId);
        if (CollUtil.isEmpty(gxFees)) {
            return new TableDataInfo(gxFees,0);
        }
        Long total = new PageInfo(gxFees).getTotal();
        List<String> feeIds = gxFees.stream().map(CusGxFee::getId).collect(Collectors.toList());
        String[] feeArrIds = feeIds.toArray(new String[feeIds.size()]);
        List<CusFeatureBo> cusFeatureBos = cusFeatureMapper.selectLinkDataAndEntity(companyId, feeArrIds ,CusConstants.GB_TYPE);
        Map<String, List<CusFeatureBo>> feeIdFeatureMap = cusFeatureBos.stream().collect(Collectors.groupingBy(CusFeatureBo::getSubpkId));
        for (CusGxFee gxFee : gxFees) {
            String feeId = gxFee.getId();
            String content = gxFee.getContent();
            String s = ParseContentUtil.parseContent(content);
            gxFee.setContent(s);
            gxFee.setBeReady(!DateUtils.isSameInstant(gxFee.getUpdateTime(),gxFee.getCreateTime()));
            List<CusFeatureBo> featureBoList = feeIdFeatureMap.get(feeId);
            if (CollUtil.isNotEmpty(featureBoList)) {
                String featureValues = featureBoList.stream().map(CusFeature::getFeatureName).collect(Collectors.joining("；"));
                gxFee.setFeatureValues(featureValues);
            }
        }
        return new TableDataInfo(gxFees,total.intValue());
    }

    /**
     * 新增工序分包费用项
     *
     * @param dmcGxFee 工序分包费用项
     * @return 结果
     */
    @Override
    public int insertDmcGxFee(CusGxFee dmcGxFee)
    {
            return cusGxFeeMapper.insert(dmcGxFee);
    }

    /**
     * 修改工序分包费用项
     *
     * @param vo 修改工序 特征 分类耗量 vo
     * @return 结果
     */
    @Override
    @Transactional
    public int updateDmcGxFee(GxFeeVo vo)
    {
        BasicInfoVo basicInfo = vo.getBasicInfo();
        String gxId = basicInfo.getId();
        Long companyId = SecurityUtils.getCompanyId();
        CusGxFee cusGxFee = this.getById(gxId, companyId);
        String specId = cusGxFee.getSpecId();
        List<String> ids = new ArrayList<>(1);
        ids.add(gxId);

        cusLinkFeatureMapper.deleteByItemIds(companyId,ids);
        List<CusLinkFeature> linkFeatureList = vo.getLinkFeatureList();
        for (CusLinkFeature lf : linkFeatureList) {
            lf.setId(gxId + "-" + lf.getFeatureId());
            lf.setCompanyId(companyId);
            lf.setItemId(gxId);
            lf.setType(CusConstants.GX_TYPE);
            if (StringUtils.equals(CusConstants.SUBJECT_TYPE, lf.getIsSubject())) {
                if (StringUtils.isEmpty(lf.getFeatureItem())) {
                    throw new RuntimeException("主项特征默认值不能为空");
                }
            } else {
                lf.setFeatureItem("");
            }
        }
        // 更新特征
        cusLinkFeatureMapper.insertBatchSomeColumn(linkFeatureList);
//        更新分类耗量
        List<CusLinkGxfeeCategory> linkCategories = vo.getLinkCategoryList();
        // 需要更新的
        List<String> idsNew = linkCategories.stream().map(CusLinkGxfeeCategory::getCategoryId).collect(Collectors.toList());
        Map<String, CusLinkGxfeeCategory> categoryNewMap = linkCategories.stream().collect(Collectors.toMap(CusLinkGxfeeCategory::getCategoryId, Function.identity()));
        // 历史记录
        List<String> idsOld = cusLinkGxfeeCategoryMapper.selectCategoriesIdByGxId(gxId, companyId);
        List<String> idsDel = cusLinkGxfeeCategoryMapper.selectCategoriesIdByGxIdDel(gxId, companyId);

        // 取新增的
        List<String> addIds = idsNew.stream().filter(item -> !idsOld.contains(item)).collect(Collectors.toList());
        // 新增的是删除的
        List<String> addDelIds = idsNew.stream().filter(idsDel::contains).collect(Collectors.toList());
        // 取删除的
        List<String> delIds = idsOld.stream().filter(item -> !idsNew.contains(item)).collect(Collectors.toList());

        if(CollUtil.isNotEmpty(addDelIds)){
            cusLinkGxfeeCategoryMapper.updateDelFlagIsZero(gxId,companyId,addDelIds);
            cusLinkSubpkConsumeMapper.updateDelFlagIsZeroByGx(gxId,companyId,addDelIds);
            cusGxLinkGkCategoriesMapper.updateDelFlagIsZero(gxId,companyId,addDelIds);
        }
        if(addIds.size()>0){
            BigDecimal bigDecimal = new BigDecimal("0.0000");
            Map<String,String> featureConsumeStateMap = JSON.parseObject(cusGxFee.getFeatureConsumeState(), Map.class);
            List<String> addressList = cusLinkSubpkConsumeAddressMapper.selectAddressList(companyId,specId);

            List<CusLinkSubpkConsume> cusLinkSubpkConsumeList = new ArrayList<>();
            // 处理地区耗量  和 关联归口
            for (String address : addressList) {
                if(StringUtils.equals(featureConsumeStateMap.get(address),"0")){
                    for (String addId : addIds) {
                        CusLinkSubpkConsume cusLinkSubpkConsume = new CusLinkSubpkConsume();
                        cusLinkSubpkConsume.setId(gxId + "-" + address + "-" + addId);
                        cusLinkSubpkConsume.setCompanyId(companyId);
                        cusLinkSubpkConsume.setAddress(address);
                        cusLinkSubpkConsume.setSpecId(specId);
                        cusLinkSubpkConsume.setSubpkItemId(gxId);
                        cusLinkSubpkConsume.setLinkGxFeatureId(gxId);
                        cusLinkSubpkConsume.setCategoriesId(addId);
                        cusLinkSubpkConsume.setRealityConsume(bigDecimal);
                        cusLinkSubpkConsume.setReferenceConsume(bigDecimal);
                        cusLinkSubpkConsume.setType(categoryNewMap.get(addId).getType());
                        cusLinkSubpkConsume.setDelFlag("0");
                        cusLinkSubpkConsumeList.add(cusLinkSubpkConsume);
                    }
                }else {
                    List<String> featureConsumeIds = cusGxFeatureConsumeMapper.selectFeatureDescribeIds(gxId, companyId,address);
                    for (String addId : addIds) {
                        for (String featureConsumeId : featureConsumeIds) {
                            CusLinkSubpkConsume cusLinkSubpkConsume = new CusLinkSubpkConsume();
                            cusLinkSubpkConsume.setId(featureConsumeId + "-" + addId);
                            cusLinkSubpkConsume.setCompanyId(companyId);
                            cusLinkSubpkConsume.setAddress(address);
                            cusLinkSubpkConsume.setSpecId(specId);
                            cusLinkSubpkConsume.setSubpkItemId(gxId);
                            cusLinkSubpkConsume.setLinkGxFeatureId(featureConsumeId);
                            cusLinkSubpkConsume.setCategoriesId(addId);
                            cusLinkSubpkConsume.setRealityConsume(bigDecimal);
                            cusLinkSubpkConsume.setReferenceConsume(bigDecimal);
                            cusLinkSubpkConsume.setType(categoryNewMap.get(addId).getType());
                            cusLinkSubpkConsume.setDelFlag("0");
                            cusLinkSubpkConsumeList.add(cusLinkSubpkConsume);
                        }
                    }
                }
            }
            if(CollUtil.isNotEmpty(cusLinkSubpkConsumeList)){
                cusLinkSubpkConsumeMapper.insertBatchSomeColumn(cusLinkSubpkConsumeList);
            }
            if(CollUtil.isNotEmpty(addIds)){
                String nullGkItemStr = getNullGkItemStr();
                List<CusLinkGxfeeCategory> addLinkCategories = new ArrayList<>();
                // 新增关联
                addIds.forEach(e -> addLinkCategories.add(categoryNewMap.get(e)));
                for (CusLinkGxfeeCategory addLinkCategory : addLinkCategories) {
                    addLinkCategory.setId(gxId + "-"+ addLinkCategory.getCategoryId());
                    addLinkCategory.setCompanyId(companyId);
                    addLinkCategory.setGxId(gxId);
                    addLinkCategory.setSpecId(specId);
                    addLinkCategory.setGkItem(nullGkItemStr);
                    addLinkCategory.setDelFlag("0");
                }
                cusLinkGxfeeCategoryMapper.insertBatchSomeColumn(addLinkCategories);
            }

            // 新增关联归口数据
            CusGxLinkGk cusGxLinkGk = cusGxLinkGkMapper.selectCusGxLinkGkById(gxId, companyId);
            if (Objects.nonNull(cusGxLinkGk)) {
                if (StringUtils.equals(cusGxLinkGk.getFeatureState(), "1")) {
                    Map<String, String> dictMap = new HashMap<>();
                    List<SysDictData> gk_categorys = DictUtils.getDictCache("gk_categorys");
                    for (SysDictData sysDictData : gk_categorys) {
                        dictMap.put(sysDictData.getDictValue(), "");
                    }
                    String nullGkItemOne = JSON.toJSONString(dictMap);

                    List<CusGxLinkGk> cusGxFeatureLinkGks = cusGxLinkGkMapper.selectCusGxLinkGkFeatureList(gxId, companyId);
                    List<CusGxLinkGkCategories> cusGxLinkGkCategoriesList = new ArrayList<>();
                    for (CusGxLinkGk cusGxFeatureLinkGk : cusGxFeatureLinkGks) {
                        String gxFeatureLinkGkId = cusGxFeatureLinkGk.getId();
                        int orderNum = cusGxLinkGkCategoriesMapper.getMaxOrderNumByLinkGkFeatureId(gxFeatureLinkGkId, companyId);

                        for (String addId : addIds) {
                            CusGxLinkGkCategories cusGxLinkGkCategories = new CusGxLinkGkCategories();
                            cusGxLinkGkCategories.setCompanyId(companyId);
                            cusGxLinkGkCategories.setSpecId(specId);
                            cusGxLinkGkCategories.setGxId(gxId);
                            cusGxLinkGkCategories.setGxLinkGkId(cusGxFeatureLinkGk.getId());
                            cusGxLinkGkCategories.setCategoriesId(addId);
                            cusGxLinkGkCategories.setGkItem(nullGkItemOne);
                            cusGxLinkGkCategories.setOrderNum(++orderNum);
                            cusGxLinkGkCategories.setDelFlag("0");
                            cusGxLinkGkCategoriesList.add(cusGxLinkGkCategories);
                        }
                    }
                    if(CollUtil.isNotEmpty(cusGxLinkGkCategoriesList)){
                        cusGxLinkGkCategoriesMapper.insertBatchSomeColumn(cusGxLinkGkCategoriesList);
                    }
                }
            }
        }

        if (delIds.size() > 0) {
            // 关联类别
            cusLinkGxfeeCategoryMapper.updateDelFlagIsTwo(companyId, gxId, delIds);
            // 关联耗量
            cusLinkSubpkConsumeMapper.updateDelFlagIsThreeByGx(gxId,companyId,delIds);
            // 删除关联归口
            cusGxLinkGkCategoriesMapper.updateDelFlagIsTwo(gxId,delIds,companyId);
        }


        // 更新工序数据
        LambdaQueryWrapper<CusGxFee> feeLambdaQueryWrapper = new LambdaQueryWrapper<>();
        feeLambdaQueryWrapper.eq(CusGxFee::getCompanyId,companyId);
        feeLambdaQueryWrapper.eq(CusGxFee::getId,gxId);

        CusGxFee fee = new CusGxFee();
        fee.setName(basicInfo.getName());
        fee.setCode(basicInfo.getCode());
        fee.setOrderNum(basicInfo.getOrderNum());
        fee.setSuitableRange(basicInfo.getSuitableRange());

        String content = ParseContentUtil.appendContent(cusGxFee.getContent(),basicInfo.getBcnrContent());
        fee.setContent(content);
        return cusGxFeeMapper.update(fee,feeLambdaQueryWrapper);
    }

    @Autowired
    private CusLinkFbGxMapper cusLinkFbGxMapper;
    @Autowired
    private CusFbFeeMapper cusFbFeeMapper;

    /**
     * 批量删除工序分包费用项
     *
     * @param ids 需要删除的工序分包费用项主键
     * @return 结果
     */
    @Override
    public int deleteDmcGxFeeByIds(String[] ids)
    {
        return cusGxFeeMapper.deleteDmcGxFeeByIds(ids);
    }

    /**
     * 删除工序分包费用项信息
     *
     * @param id 工序分包费用项主键
     * @return 结果
     */
    @Override
    public int deleteDmcGxFeeById(String id)
    {
        return cusGxFeeMapper.deleteDmcGxFeeById(id);
    }


    @Autowired
    private CusFeatureMapper cusFeatureMapper;
    @Autowired
    private CusLinkGxfeeCategoryMapper dmcLinkGxfeeCategoryMapper;

    @Override
    public FeeLinkFeatureAndCategoryResultBo getGxFeeInfo(String id, Long companyId) {

        FeeLinkFeatureAndCategoryResultBo resultBo = cusGxFeeMapper.selectDmcGxFeeById(id, companyId);
        // 基础信息
        String content = resultBo.getContent();
        resultBo.setContent(ParseContentUtil.parseContent(content));
        resultBo.setBcnrContent(content);
        // 关联的特征
        List<FeatureRes> featureRess = cusFeatureMapper.selectLinkDataAndEntityCopyOne(companyId, id, CusConstants.GX_TYPE);
        featureRess.forEach(e -> e.setIsSubject(StringUtils.equals(e.getIsSubjectStr(),CusConstants.ENABLE_Y_TYPE)));
        resultBo.setFeatureResList(featureRess);

        // 材机分类关联
        resultBo.setCjflList(dmcLinkGxfeeCategoryMapper.selectLinkDataAndEntity(companyId,id));
        return resultBo;
    }

    @Override
    public CusRewriteCodeRequest getCodeLayout(String specId) {
        List<SysDictData> fee_projecttype = DictUtils.getDictCache("fee_projecttype");
        Map<String, String> dictMap = fee_projecttype.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getRemark));
        CusRewriteCodeRequest codeRequest = new CusRewriteCodeRequest();
        codeRequest.setPrefix(dictMap.get(specId));
        codeRequest.setSuffixLen(cusGxFeeMapper.countByChapterId(SecurityUtils.getCompanyId(),specId));
        return codeRequest;
    }

    private CusGxFee getById(String id, Long companyId) {
        CusGxFee dmcGxFee = cusGxFeeMapper.selectOne(
                Wrappers.<CusGxFee>lambdaQuery()
                        .eq(CusGxFee::getCompanyId, companyId)
                        .eq(CusGxFee::getId, id)
        );
        return dmcGxFee;
    }

    @Override
    @Transactional
    public int rewriteCode(CusRewriteCodeRequest codeRequest) {
        Long companyId = SecurityUtils.getCompanyId();
        String specId = codeRequest.getSpecId();
        int countNotClassifiedFee = cusGxFeeMapper.countNotAllot(companyId, specId, CusConstants.CHAPTER_ID_NULL);
        if(countNotClassifiedFee != 0){
            throw new ServiceException("存在未分配章节的费用项");
        }
        Integer suffixLen = codeRequest.getSuffixLen();
        Integer maxCountLen = cusGxFeeMapper.countByChapterId(companyId,specId);
        if(suffixLen < maxCountLen){
            throw new RuntimeException("根据费用项数量统计,编码后缀不能少于" + maxCountLen + "位");
        }
        cusGxFeeMapper.recodeGx(companyId,specId,codeRequest.getPrefix(),suffixLen);
        return 1;
    }

    @Override
    public List<CusGxFee> validateCode(Long companyId,String specId) {
        int countNotClassifiedFee = cusGxFeeMapper.countNotAllot(companyId, specId, CusConstants.CHAPTER_ID_NULL);
        if(countNotClassifiedFee != 0){
            throw new ServiceException("存在未分配章节的费用项");
        }
        List<CusGxFee> cusGxFeeItems = new ArrayList<>();
        LambdaQueryWrapper<CusGxFee> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CusGxFee::getCompanyId, companyId);
        wrapper.eq(CusGxFee::getSpecId, specId);
        wrapper.groupBy(CusGxFee::getCode);
        wrapper.having("count(*) > 1 or `code`='' or ISNULL(`code`)");
        cusGxFeeItems = cusGxFeeMapper.selectList(wrapper);
        return cusGxFeeItems;
    }

    @Override
    public StaGxFee getStaGxFeeById(String id, String specId, Long companyId) {
        String newestId = staVersionMapper.getNewestId(companyId,CusConstants.GX_TYPE,specId);
        return staGxFeeMapper.selectStaGxFeeById(newestId,id);
    }

    @Override
    @Transactional
    public List<CJFlRes> recoverLinkCategory(String id, Long companyId) {
        if(StringUtils.isEmpty(id)){
            throw new ServiceException("id为空");
        }
        cusLinkGxfeeCategoryMapper.updateDelFlagIsZero(id,companyId,null);
        cusLinkSubpkConsumeMapper.updateDelFlagIsZeroByGx(id,companyId,null);
        cusGxLinkGkCategoriesMapper.updateDelFlagIsZero(id,companyId,null);
        return dmcLinkGxfeeCategoryMapper.selectLinkDataAndEntity(companyId, id);
    }

    @Override
    public List<CJFlRes> getGxLinkCategory(String id, Long companyId) {
        return dmcLinkGxfeeCategoryMapper.selectLinkDataAndEntity(companyId,id);
    }

    @Override
    public int moveToChapter(String[] ids, String chapterId) {
        cusGxFeeMapper.updateChapterIdByIds(ids,chapterId,SecurityUtils.getCompanyId());
        return 1;
    }

    @Override
    public CusFeatureStateVo checkFeatureDescribe(String gxId, String featureId) {
        Long companyId = SecurityUtils.getCompanyId();
        CusFeatureStateVo assetFeatureStateVo = new CusFeatureStateVo();
        Integer gkFeatureState = cusGxLinkGkMapper.checkFeatureDescribe(companyId, gxId, featureId);
        List<String> addressList = cusGxFeatureConsumeMapper.checkFeatureDescribe(companyId, gxId, featureId);
        assetFeatureStateVo.setGk(gkFeatureState);
        assetFeatureStateVo.setAddressList(addressList);
        return assetFeatureStateVo;
    }

    private String getNullGkItemStr(){
        List<SysDictData> gk_categorys = DictUtils.getDictCache("gk_categorys");
        if (CollUtil.isEmpty(gk_categorys)) {
            throw new ServiceException("字典获取失败");
        }
        return JSON.toJSONString(gk_categorys.stream().collect(Collectors.toMap(SysDictData::getDictValue, value -> "")));
    }
}
